// gcc -g -rdynamic glibc_backtrace_signal.c -o glibc_backtrace_signal
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <execinfo.h>
#include <signal.h>

#define BT_BUF_SIZE 100
void print_backtrace() {
    void *bt_buffer[BT_BUF_SIZE];
    int bt_size = backtrace(bt_buffer, BT_BUF_SIZE);
    char **bt_strings = backtrace_symbols(bt_buffer, bt_size);
    printf("backtrace:\n");
    for (int i = 0; i < bt_size; i++) {
        printf("[#%d] %s\n", i, bt_strings[i]);
    }
    free(bt_strings);
    bt_strings = NULL;
    exit(EXIT_SUCCESS);
}

void my_signal_handler(int sig)
{
    print_backtrace();
}

void func3()
{
    int *ptr = NULL;
    *ptr = 123;
}

void func2()
{
    func3();
}

void func1()
{
    func2();
}

int main()
{
    if (signal(SIGSEGV, my_signal_handler) == SIG_ERR)
        perror("can't catch SIGSEGV");
    func1();
    return 0;
}
